package com.cares.core.mng.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springside.modules.security.utils.Digests;
import org.springside.modules.utils.DateProvider;
import org.springside.modules.utils.Encodes;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.cares.core.base.service.BaseService;
import com.cares.core.base.service.ServiceException;
import com.cares.core.mng.repository.UserMybatisDao;
import com.cares.core.utils.Constant;
import com.cares.core.utils.StringUtil;
import com.cares.entity.base.PageModel;
import com.cares.entity.mng.Orgnization;
import com.cares.entity.mng.User;

import com.google.common.collect.Maps;

/**
 * 
 * @author calvin
 */
//Spring Service Bean的标识.
@Service("accountService")
@Transactional
public class AccountService extends BaseService {

	public static final String HASH_ALGORITHM = "SHA-1";
	public static final int HASH_INTERATIONS = 1024;
	private static final int SALT_SIZE = 8;
	private DateProvider dateProvider = DateProvider.DEFAULT;

	private static Logger logger = LoggerFactory
			.getLogger(AccountService.class);
	@Autowired
	UserMybatisDao userDao;
	
	@Autowired
	@Qualifier("orgService")
	OrgService orgService;

	public final String DEFAULT_PWD = "123456";

	/**
	 * 先访问Memcached, 使用JSON字符串存放对象以节约空间.
	 */
	public User getUser(Long id) {

		User user = null;
		user = userDao.get(id);
		user.setOrgnization(orgService.get(user.getOrgCode()));
		return user;
	}
	
	/**
	 * 根据登录名查询用户信息
	 * 登录名唯一性校验
	 * @param loginName
	 * @return
	 */
	public User findUserByLoginName(String loginName) {
		return findUserByLoginName(loginName, false);
	}
	
	/**
	 * 根据登录名查询用户信息，并返回用户的Org信息
	 * @param loginName
	 * @param all
	 * @return
	 */
	public User findUserByLoginName(String loginName, boolean all) {
		List<User> listUser = searchUser(loginName, null);
		User user = null;
		if (null != listUser && listUser.size() > 0) {
			user = listUser.get(0);
			if (all)
				user.setOrgnization(orgService.get(user.getOrgId()));
		}
		return user;
	}
	
	/**
	 * 根据登录名或用户名查询用户信息
	 * @param loginName
	 * @param name
	 * @return
	 */
	public List<User> searchUser(String loginName, String name) {
		try {
			Map<String, Object> parameters = Maps.newHashMap();
			parameters.put("loginName", loginName);
			parameters.put("name", name);
			return userDao.search(parameters);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 新增用户信息
	 * @param user
	 * @throws Exception
	 */
	public void updateNewUser(User user) throws Exception {
		user.setPlainPassword(DEFAULT_PWD);// 新用户默认密码
		entryptPassword(user);
		user.setRoles("user");
		user.setRegisterDate(dateProvider.getDate());
		user.setCreateTime(dateProvider.getDate());
		user.setCreateUser(getCurrentUserName());
		Orgnization org = orgService.get(user.getOrgId());
		if(org!=null && StringUtils.isNotEmpty(org.getOrgPath())) {
			user.setOrgCode(org.getOrgCode());
			user.setOrgPath(org.getOrgPath());
		} else {
			user.setOrgCode(super.getCurrentUserOrgCode());
			user.setOrgPath(super.getCurrentUserOrgPath());
		}
		user.setState(Constant.USER_STATE_OK);
		saveUser(user);
	}
	
	/**
	 * 更新用户信息
	 * @param user
	 */
	public void updateUser(User user) {
		if (StringUtils.isNotBlank(user.getPlainPassword())) {
			entryptPassword(user);
		}
		user.setUpdateTime(dateProvider.getDate());
		user.setUpdateUser(getCurrentUserName());
		if (!super.getCurrentUser().isSuperMan())
			user.setOrgCode(null);// 所在机构不得修改
		userDao.update(user);
	}
	
	/**
	 * 密码更新
	 * @param userId
	 * @param newpwd
	 * @param oldpwd
	 * @return
	 * @throws Exception
	 */
	public int updateUserPwd(Long userId, String newpwd, String oldpwd)
			throws Exception {
		User user = userDao.get(userId);
		if (null == user)
			return 0;

		String pwd = getEntryptPassword(oldpwd, user.getSalt());
		if (pwd.equals(user.getPassword())) {
			user.setSalt(null);
			user.setPlainPassword(newpwd);
			entryptPassword(user);
			userDao.updatePass(user);
			return 1;
		} else {
			return 0;
		}
	}

	/**
	 * 密码重置
	 * @param userId
	 * @param newpwd
	 * @param oldpwd
	 * @return
	 * @throws Exception
	 */
	public int updateResetUserPwd(Long userId, String newpwd, String oldpwd)
			throws Exception {
		User user = userDao.get(userId);
		if (null == user)
			return 0;

		user.setPlainPassword(newpwd);
		entryptPassword(user);
		userDao.updatePass(user);
		return 1;

	}

	/**
	 * 判断是否超级管理员.
	 */
	private boolean isSupervisor(Long id) {
		return id == 1;
	}

	/**
	 * 设定安全的密码，生成随机的salt并经过1024次 sha-1 hash
	 */
	private void entryptPassword(User user) {
		byte[] salt = Digests.generateSalt(SALT_SIZE);
		user.setSalt(Encodes.encodeHex(salt));
		byte[] hashPassword = null;
		// 如果没有密码则使用用户的登录名作为默认密码
		if (null != user.getPlainPassword()) {
			hashPassword = Digests.sha1(user.getPlainPassword().getBytes(),
					salt, HASH_INTERATIONS);
		}

		else {
			hashPassword = Digests.sha1(user.getLoginName().getBytes(), salt,
					HASH_INTERATIONS);
		}
		user.setPassword(Encodes.encodeHex(hashPassword));
	}
	
	/**
	 * 密码加密
	 * @param plainPassword
	 * @param salt
	 * @return
	 */
	private String getEntryptPassword(String plainPassword, String salt) {
		byte[] saltb = Encodes.decodeHex(salt);
		byte[] hashPassword = null;
		hashPassword = Digests.sha1(plainPassword.getBytes(), saltb,
				HASH_INTERATIONS);
		return Encodes.encodeHex(hashPassword);
	}
	
	/**
	 * 用户新增
	 * @param user
	 */
	public void saveUser(User user) {
		entryptPassword(user);
		user.setRoles("user");
		user.setRegisterDate(dateProvider.getDate());
		userDao.save(user);
	}

	/**
	 * 用户角色更新
	 * @param user
	 */
	public void updateUserRoles(User user) {
		userDao.deleteRolesById(user.getId());
		if (null != user.getSysroleids() && !"".equals(user.getSysroleids())) {
			String[] arr = user.getSysroleids().split(",");
			Map param = new HashMap();
			param.put("uid", user.getId());
			for (String id : arr) {
				param.put("rid", Long.valueOf(id));
				userDao.insertRolesById(param);
			}

		}
	}

	/**
	 * 根据用户id逻辑删除用户
	 * @param id
	 */
	public void deleteUser(Long id) {
		if (isSupervisor(id)) {
			logger.warn("操作员{}尝试删除超级管理员用户", getCurrentUserName());
			throw new ServiceException("不能删除超级管理员用户");
		}
		User user = getUser(id);
		user.setState(Constant.USER_STATE_LOCK);
		user.setUpdateTime(dateProvider.getDate());
		user.setUpdateUser(getCurrentUserName());
		userDao.update(user);
	}
	
	/**
	 * 新的按照org的方式查询user，这是一个通用的方法
	 * @param pageModel
	 * @return
	 */
	public String getOrgUsers(PageModel<User> pageModel) {
		String result = "";
		JSONObject json = new JSONObject();
	
		User condition = (User) pageModel.getCondition();
		try {
			List<User> users = new ArrayList<User>();
			if (condition == null || condition.getOrgId() == null) {
				condition.setOrgPath(getCurrentUserOrgPath());
				users = this.userDao.getAllByOrg(pageModel);

				json.put("total", this.userDao.countByOrg(pageModel));
			} else {
				users = this.userDao.getAll(pageModel);
				json.put("total", this.userDao.count(pageModel));
			}
			StringBuffer rolename = null;
			StringBuffer roleid = null;
			for (User user : users) {
				roleid = new StringBuffer();
				rolename = new StringBuffer();
				List<Map> roleMaps = userDao.getUserRolesById(user.getId());
				for (int i = 0; i < roleMaps.size(); i++) {
					if (i == 0) {
						roleid.append(roleMaps.get(i).get("rid"));
						rolename.append(roleMaps.get(i).get("roleName"));
					} else {
						roleid.append("," + roleMaps.get(i).get("rid"));
						rolename.append("," + roleMaps.get(i).get("roleName"));
					}
				}
				Orgnization org = orgService.get(user.getOrgId());
				if(org!=null) {
					user.setOrgNameCn(org.getNameCn());
				}
				user.setSysroleids(roleid.toString());
				user.setSysroles(rolename.toString());
			}
			json.put("rows", JSON.toJSON(users));
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		result = json.toString();
		return result;
	}
	
	/**
	 * 根据orgCode左连接查询用户信息
	 * @param pageModel
	 * @return
	 */
	public String getUsers(PageModel pageModel) {
		String result = "";
		JSONObject json = new JSONObject();
		List<Map> rows = new ArrayList<Map>();
		List<User> users = this.userDao.getAll(pageModel);
		StringBuffer rolename = null;
		StringBuffer roleid = null;
		for (User user : users) {
			roleid = new StringBuffer();
			rolename = new StringBuffer();
			List<Map> roleMaps = userDao.getUserRolesById(user.getId());
			for (int i = 0; i < roleMaps.size(); i++) {
				if (i == 0) {
					roleid.append(roleMaps.get(i).get("rid"));
					rolename.append(roleMaps.get(i).get("roleName"));
				} else {
					roleid.append("," + roleMaps.get(i).get("rid"));
					rolename.append("," + roleMaps.get(i).get("roleName"));
				}
			}
			Orgnization org = orgService.get(user.getOrgId());
			if(org!=null) {
				user.setOrgNameCn(org.getNameCn());
			}
			Map<String, Object> row = new HashMap<String, Object>();
			row.put("name", user.getName());
			row.put("id", user.getId());
			row.put("email", user.getEmail());
			row.put("loginName", user.getLoginName());
			row.put("roles", user.getRoles());
			row.put("orgCode", user.getOrgCode());
			row.put("orgId", user.getOrgId());
			if (null != user.getOrgCode())
				row.put("orgNameCn", "[ " + user.getOrgCode() + " ] "
						+ user.getOrgNameCn());
			row.put("sysroles", rolename.toString());
			row.put("sysroleids", roleid.toString());
			rows.add(row);
		}

		try {
			json.put("total", this.userDao.count(pageModel));
			json.put("rows", rows);
			result = json.toString();
		} catch (JSONException e) {
		}

		return result;
	}
}
